package com.mall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.common.utils.R;
import com.common.vo.MemberVo;
import com.common.vo.SkuInfoVo;
import com.mall.cart.Feign.ProductServiceFeign;
import com.mall.cart.Interceptor.AuthInterceptor;
import com.mall.cart.constants.CartConstants;
import com.mall.cart.service.ICartService;
import com.mall.cart.vo.Cart;
import com.mall.cart.vo.CartItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * 购物车信息存储再redis
 */
@Service
public class ICartServiceImpl implements ICartService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProductServiceFeign productServiceFeign;
    @Autowired
    ThreadPoolExecutor threadPoolExecutor;
    @Override
    public Cart getCartList() {
        BoundHashOperations<String, Object, Object> cartKey = getCartKey();
        Set<Object> keys =cartKey.keys();
        Cart cart = new Cart();
        List<CartItem> cartItemList = new ArrayList<>();
        for (Object k : keys) {
            String key = (String) k;
            Object object = cartKey.get(key);
            String json = (String) object;
            CartItem item = JSON.parseObject(json, CartItem.class);
            cartItemList.add(item);
        }
        cart.setItems(cartItemList);
        return cart;
    }

    @Override
    public CartItem addCart(String skuId, Integer num) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, Object, Object> operations = getCartKey();
        Object o = operations.get(skuId);
        if (o != null){
            String json = (String) o;
            CartItem cartItem = JSON.parseObject(json, CartItem.class);
            cartItem.setCount(cartItem.getCount() + num);
            return cartItem;
        }
        CartItem item = new CartItem();
        CompletableFuture future1 = CompletableFuture.runAsync(()-> {
                    R info = productServiceFeign.info(Long.valueOf(skuId));
                    SkuInfoVo skuInfo = (SkuInfoVo) info.get("skuInfo");
                    item.setCheck(true);
                    item.setCount(num);
                    item.setPrice(skuInfo.getPrice());
                    item.setImage(skuInfo.getSkuDefaultImg());
                    item.setSkuId(Long.parseLong(skuId));
                    item.setTitle(skuInfo.getSkuTitle());},threadPoolExecutor
        );
                CompletableFuture future2 = CompletableFuture.runAsync(()-> {
                            List<String> attrs = productServiceFeign.getSkuSaleAttrs(Long.parseLong(skuId));
                            item.setSkuAttr(attrs);},threadPoolExecutor);
        CompletableFuture.allOf(future1,future2).get();
        String itemJson = JSON.toJSONString(item);
        operations.put(skuId,itemJson);
        return item;
    }
    private BoundHashOperations<String, Object, Object> getCartKey() {
        // hash key: cart:1   skuId:cartItem
        MemberVo memberVO = AuthInterceptor.threadLocal.get();
        String cartKey = CartConstants.CART_PERFIX + memberVO.getId();
        BoundHashOperations<String, Object, Object> hashOperations = redisTemplate.boundHashOps(cartKey);
        return hashOperations;
    }

    @Override
    public List<CartItem> getUserCartItems() {
//        MemberVo memberVo = AuthInterceptor.threadLocal.get();
//        String cartKey = CartConstants.CART_PERFIX + memberVo.getId();
        BoundHashOperations<String, Object, Object> cartKey = getCartKey();
        List<Object> values = cartKey.values();
        List<CartItem> cartItems = values.stream().map(item -> {
            String json = (String) item;
            CartItem cartItem = JSON.parseObject(json, CartItem.class);
            return cartItem;
        }).filter(CartItem::isCheck).collect(Collectors.toList());

        return cartItems;
    }
}
